const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const validator = require('validator');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');

const userSchema = new mongoose.Schema({
  username: {
    type: String,
    required: [true, '请输入用户名'],
    unique: true,
    trim: true,
    minlength: [3, '用户名不能少于3个字符'],
    maxlength: [20, '用户名不能超过20个字符'],
    match: [/^[a-zA-Z0-9_]+$/, '用户名只能包含字母、数字和下划线']
  },
  email: {
    type: String,
    required: [true, '请输入邮箱地址'],
    unique: true,
    trim: true,
    lowercase: true,
    validate: [validator.isEmail, '请输入有效的邮箱地址']
  },
  password: {
    type: String,
    required: [true, '请输入密码'],
    minlength: [6, '密码不能少于6个字符'],
    select: false
  },
  avatar: {
    type: String,
    default: 'https://myblogapp.oss-cn-beijing.aliyuncs.com/default-avatar.jpg'
  },
  bio: {
    type: String,
    maxlength: [200, '个人简介不能超过200个字符'],
    default: '这个人很懒，什么都没有留下~'
  },
  role: {
    type: String,
    enum: {
      values: ['user', 'admin'],
      message: '角色只能是user或admin'
    },
    default: 'user'
  },
  status: {
    type: String,
    enum: ['active', 'suspended', 'banned'],
    default: 'active'
  },
  followers: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  }],
  following: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  }],
  followerCount: {
    type: Number,
    default: 0
  },
  followingCount: {
    type: Number,
    default: 0
  },
  postCount: {
    type: Number,
    default: 0
  },
  resetPasswordToken: String,
  resetPasswordExpire: Date,
  emailVerified: {
    type: Boolean,
    default: false
  },
  emailVerificationToken: String,
  emailVerificationExpire: Date,
  lastLoginAt: Date,
  loginCount: {
    type: Number,
    default: 0
  }
}, {
  timestamps: true,
  toJSON: { virtuals: true },
  toObject: { virtuals: true }
});

// 密码加密中间件
userSchema.pre('save', async function(next) {
  if (!this.isModified('password')) return next();
  
  try {
    const salt = await bcrypt.genSalt(10);
    this.password = await bcrypt.hash(this.password, salt);
    next();
  } catch (err) {
    next(err);
  }
});

// 密码验证方法
userSchema.methods.comparePassword = async function(candidatePassword) {
  return await bcrypt.compare(candidatePassword, this.password);
};

// 生成JWT令牌
userSchema.methods.generateAuthToken = function() {
  return jwt.sign(
    { id: this._id, role: this.role },
    "11111112324",
    { expiresIn: '30d' }
  );
};

// 生成密码重置令牌
userSchema.methods.generateResetPasswordToken = function() {
  const resetToken = crypto.randomBytes(20).toString('hex');
  
  this.resetPasswordToken = crypto
    .createHash('sha256')
    .update(resetToken)
    .digest('hex');
  
  this.resetPasswordExpire = Date.now() + 10 * 60 * 1000; // 10分钟有效
  
  return resetToken;
};

// 生成邮箱验证令牌
userSchema.methods.generateEmailVerificationToken = function() {
  const verificationToken = crypto.randomBytes(20).toString('hex');
  
  this.emailVerificationToken = crypto
    .createHash('sha256')
    .update(verificationToken)
    .digest('hex');
  
  this.emailVerificationExpire = Date.now() + 24 * 60 * 60 * 1000; // 24小时有效
  
  return verificationToken;
};

// 获取用户简略信息(用于公开展示)
userSchema.methods.getProfile = function() {
  return {
    _id: this._id,
    username: this.username,
    avatar: this.avatar,
    bio: this.bio,
    followerCount: this.followerCount,
    followingCount: this.followingCount,
    postCount: this.postCount,
    createdAt: this.createdAt
  };
};

// 静态方法 - 通过邮箱查找用户
userSchema.statics.findByEmail = function(email) {
  return this.findOne({ email }).select('+password');
};

// 静态方法 - 通过用户名查找用户
userSchema.statics.findByUsername = function(username) {
  return this.findOne({ username });
};

// 静态方法 - 检查用户名或邮箱是否已存在
userSchema.statics.checkExists = async function(username, email) {
  const user = await this.findOne({
    $or: [{ username }, { email }]
  });
  
  const errors = {};
  if (user) {
    if (user.username === username) {
      errors.username = '该用户名已被使用';
    }
    if (user.email === email) {
      errors.email = '该邮箱已被注册';
    }
  }
  
  return {
    exists: !!user,
    errors: Object.keys(errors).length > 0 ? errors : null
  };
};


// 静态方法 - 查找用户（通过用户名或邮箱）
userSchema.statics.findByCredentials = async function(identifier, password) {
  const user = await this.findOne({
    $or: [{ username: identifier }, { email: identifier }]
  }).select('+password');

  if (!user) {
    throw new Error('用户名或邮箱不存在');
  }

  const isMatch = await user.comparePassword(password);

  if (!isMatch) {
    throw new Error('密码错误');
  }

  return user;
};

// 虚拟属性 - 用户文章
userSchema.virtual('posts', {
  ref: 'Post',
  localField: '_id',
  foreignField: 'author'
});

// 更新关注数统计
userSchema.pre('save', function(next) {
  if (this.isModified('followers')) {
    this.followerCount = this.followers.length;
  }
  if (this.isModified('following')) {
    this.followingCount = this.following.length;
  }
  next();
});

// 用户名转小写处理
userSchema.pre('save', function(next) {
  if (this.isModified('username')) {
    this.username = this.username.toLowerCase();
  }
  next();
});

const User = mongoose.model('User', userSchema);

module.exports = User;